//
//  ZHQRScanView.m
//  ZHQRScan
//
//  Created by 正合适 on 2017/11/18.
//  Copyright © 2017年 Rainy. All rights reserved.
//

#import "ZHQRScanView.h"
#import "ZHQRScanMacro.h"
#import <AVFoundation/AVFoundation.h>

@interface ZHQRScanView ()<AVCaptureMetadataOutputObjectsDelegate>

/**配置*/
@property (nonatomic, strong) ZHQRScanConfig *config;
/**横线*/
@property (nonatomic, strong) UIImageView *animationLine;
/**设备*/
@property (nonatomic, strong) AVCaptureDevice *captureDevice;
/**输入*/
@property (nonatomic, strong) AVCaptureDeviceInput *captureInput;
/**输出*/
@property (nonatomic, strong) AVCaptureMetadataOutput *captureOut;
/**session*/
@property (nonatomic, strong) AVCaptureSession *session;
/**展示内容*/
@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;

@end

@implementation ZHQRScanView
#pragma mark - 生命周期
- (instancetype)initWithFrame:(CGRect)frame config:(ZHQRScanConfig *)config {
    self = [super initWithFrame:frame];
    if (self) {
        _config = [config?config:[ZHQRScanConfig alloc] init];
        [self main];
    }
    return self;
}

- (instancetype)initWithFrame:(CGRect)frame {
    return [self initWithFrame:frame config:nil];
}

- (void)dealloc {
    NSLog(@"--- ZHQRScanView 被移除 ---");
}

#pragma mark - 入口
- (void)main {
    [self createUI];
    [self createMaskView];
    [self initialQR];
    // 开启动画
    [self lineAnimationAction];
}

#pragma mark - 初始化UI
- (void)createUI {
    float x = (self.frame.size.width-kScanRangeW)/2.0;
    float y = (self.frame.size.height-kScanRangeW)/2.0;
    UIImageView *scanRangeView = [[UIImageView alloc] initWithFrame:CGRectMake(x, y, kScanRangeW, kScanRangeW)];
    scanRangeView.image = [UIImage imageNamed:@"ZHUIKit.bundle/ZHQRScanPick_bg"];
    [self addSubview:scanRangeView];
    
    _animationLine = [[UIImageView alloc] initWithFrame:CGRectMake(x, y+5, scanRangeView.frame.size.width, 2)];
    _animationLine.image = [UIImage imageNamed:@"ZHUIKit.bundle/ZHQRScanLine"];
    [self addSubview:_animationLine];
}

#pragma mark - 初始化扫描设备
- (void)initialQR {
    _captureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    if (!_captureDevice) {
        // 设备不支持
        if (self.delegate && [self.delegate respondsToSelector:@selector(deviceUnsupport)]) {
            [self.delegate deviceUnsupport];
        }
        return;
    }
    _captureInput = [AVCaptureDeviceInput deviceInputWithDevice:_captureDevice error:nil];
    
    _captureOut = [[AVCaptureMetadataOutput alloc] init];
    [_captureOut setMetadataObjectsDelegate:self queue:dispatch_get_main_queue()];
    CGFloat top = (self.frame.size.height-kScanRangeW)/2/self.frame.size.height;
    CGFloat left = (self.frame.size.width-kScanRangeW)/2/self.frame.size.width;
    CGFloat width = kScanRangeW/self.frame.size.width;
    CGFloat height = kScanRangeW/self.frame.size.height;
    ///top 与 left 互换  width 与 height 互换
    [_captureOut setRectOfInterest:CGRectMake(top,left, height, width)];
    
    _session = [[AVCaptureSession alloc] init];
    [_session setSessionPreset:AVCaptureSessionPresetHigh];
    if ([_session canAddInput:_captureInput]) [_session addInput:_captureInput];
    if ([_session canAddOutput:_captureOut]) [_session addOutput:_captureOut];
    // 添加扫描类型
    [_captureOut setMetadataObjectTypes:[self qrScanType]];
    
    _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill;
    _previewLayer.frame = self.layer.bounds;
    [self.layer insertSublayer:_previewLayer atIndex:0];
    [_session startRunning];
}

#pragma mark - 横线动画
- (void)lineAnimationAction {
    CABasicAnimation *lineAnimation = [CABasicAnimation animationWithKeyPath:@"position.y"];
    lineAnimation.duration = _config.animationDuration;
    lineAnimation.fromValue = @((self.frame.size.height-kScanRangeW)/2.0+5);
    lineAnimation.toValue = @((self.frame.size.height-kScanRangeW)/2.0+kScanRangeW-5);
    lineAnimation.repeatCount = HUGE_VALF;
    lineAnimation.autoreverses = YES;
    lineAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
    lineAnimation.fillMode = kCAFillModeForwards;
    lineAnimation.removedOnCompletion = NO;
    [_animationLine.layer addAnimation:lineAnimation forKey:@"lineAnimation"];
}

#pragma mark - 设置蒙层
- (void)createMaskView {
    float x = (self.frame.size.width-kScanRangeW)/2.0;
    float y = (self.frame.size.height-kScanRangeW)/2.0;
    CGRect cropRect = CGRectMake(x, y, kScanRangeW, kScanRangeW);
    CAShapeLayer *maskView = [[CAShapeLayer alloc] init];
    CGMutablePathRef path = CGPathCreateMutable();
    CGPathAddRect(path, nil, cropRect);
    CGPathAddRect(path, nil, self.bounds);
    [maskView setFillRule:kCAFillRuleEvenOdd];
    [maskView setPath:path];
    [maskView setFillColor:[UIColor blackColor].CGColor];
    [maskView setOpacity:0.6];
    [maskView setNeedsDisplay];
    [self.layer addSublayer:maskView];
}

#pragma mark - 扫码类型
- (NSArray *)qrScanType {
    NSArray *types = @[AVMetadataObjectTypeQRCode,
                       AVMetadataObjectTypeEAN13Code,
                       AVMetadataObjectTypeEAN8Code,
                       AVMetadataObjectTypeUPCECode,
                       AVMetadataObjectTypeCode39Code,
                       AVMetadataObjectTypeCode39Mod43Code,
                       AVMetadataObjectTypeCode93Code,
                       AVMetadataObjectTypeCode128Code,
                       AVMetadataObjectTypePDF417Code];
    return types;
}

#pragma mark - AVCaptureMetadataOutputObjectsDelegate
- (void)captureOutput:(AVCaptureOutput *)output didOutputMetadataObjects:(NSArray<__kindof AVMetadataObject *> *)metadataObjects fromConnection:(AVCaptureConnection *)connection {
    if (metadataObjects.count > 0) {
        [_session stopRunning];
        if (self.delegate && [self.delegate respondsToSelector:@selector(qrScanEnd:result:)]) {
            AVMetadataMachineReadableCodeObject *metadataObject = [metadataObjects objectAtIndex:0];
            [self.delegate qrScanEnd:ScanStatus_Success result:metadataObject.stringValue];
        }
    } else {
        if (self.delegate && [self.delegate respondsToSelector:@selector(qrScanEnd:result:)]) {
            [self.delegate qrScanEnd:ScanStatus_NoResults result:nil];
        }
    }
}
@end
